#pragma once

#include <log4cpp/Category.hh>
#include <iostream>
#include <string>

#define log_debug(log_fmt, log_arg...) \
    do { \
        log4cpp_helper::Logger::getInstance()->log(log4cpp::Priority::PriorityLevel::DEBUG, "[%s:%d][%s] " log_fmt, \
                                                  __FILE__, __LINE__, __FUNCTION__, ##log_arg); \
    } while (0)
#define log_info(log_fmt, log_arg...) \
    do { \
        log4cpp_helper::Logger::getInstance()->log(log4cpp::Priority::PriorityLevel::INFO, "[%s:%d][%s] " log_fmt, \
                                                  __FILE__, __LINE__, __FUNCTION__, ##log_arg); \
    } while (0)
#define log_warn(log_fmt, log_arg...) \
    do { \
        log4cpp_helper::Logger::getInstance()->log(log4cpp::Priority::PriorityLevel::WARN, "[%s:%d][%s] " log_fmt, \
                                                  __FILE__, __LINE__, __FUNCTION__, ##log_arg); \
    } while (0)
#define log_error(log_fmt, log_arg...) \
    do { \
        log4cpp_helper::Logger::getInstance()->log(log4cpp::Priority::PriorityLevel::ERROR, "[%s:%d][%s] " log_fmt, \
                                                  __FILE__, __LINE__, __FUNCTION__, ##log_arg); \
    } while (0)
#define log_error_t(tag, log_fmt, log_arg...) \
    do { \
        log4cpp_helper::Logger::getInstance()->log(log4cpp::Priority::PriorityLevel::ERROR, "[%s:%d][%s][tag=%s] " log_fmt, \
                                                  __FILE__, __LINE__, __FUNCTION__, tag, ##log_arg); \
    } while (0)

namespace log4cpp_helper {

// 单例日志类: Logger
class Logger {
 public:
    static Logger* getInstance() {
        return instance_;
    }

    // 初始化
    void init(const std::string& cfg_path);
    // 打印日志
    void log(log4cpp::Priority::PriorityLevel priority, const char* stringFormat, ...);

 private:
    // 单例类： 构造函数和析构函数都私有化
    Logger();
    ~Logger();
    static Logger* instance_;

    // Category:
    // 1) root输出到控制台
    // 2) info输出到info日志
    // 3) error输出到error日志
    log4cpp::Category &rootCategory_;
    log4cpp::Category &infoCategory_;
    log4cpp::Category &errorCategory_;
};

}  // namespace log4cpp_helper
